package org.jvm.util;

import org.jvm.rtda.Object;
import org.jvm.rtda.heap.Klass;
import org.jvm.rtda.heap.classLoader.*;
import org.jvm.rtda.heap.classmember.Method;
import org.jvm.rtda.thread.Thread;

/**
 * 装箱工具
 *
 * @author 海燕
 * @date 2023/3/26
 */
public class BoxUtil {

    /**
     * 将jvm的基本类型进行装箱，返回一个对应的java实例
     *
     * @param val
     * @return
     */
    public static Object box(Thread thread, java.lang.Object val) {
        if (val instanceof Object) {
            return (Object) val;
        }
        //负责装箱的方法
        Method boxMethod = null;
        BootKlassLoader bootKlassLoader = KlassLoaderRegister.getBootKlassLoader();
        if (val instanceof Integer) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Integer");
            boxMethod = klass.getStaticMethod("valueOf", "(I)Ljava/lang/Integer;");
        } else if (val instanceof Long) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Long");
            boxMethod = klass.getStaticMethod("valueOf", "(J)Ljava/lang/Long;");
        } else if (val instanceof Boolean) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Boolean");
            boxMethod = klass.getStaticMethod("valueOf", "(Z)Ljava/lang/Boolean;");
        } else if (val instanceof Byte) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Byte");
            boxMethod = klass.getStaticMethod("valueOf", "(B)Ljava/lang/Byte;");
        } else if (val instanceof Character) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Character");
            boxMethod = klass.getStaticMethod("valueOf", "(C)Ljava/lang/Character;");
        } else if (val instanceof Short) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Short");
            boxMethod = klass.getStaticMethod("valueOf", "(S)Ljava/lang/Short;");
        } else if (val instanceof Float) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Float");
            boxMethod = klass.getStaticMethod("valueOf", "(F)Ljava/lang/Float;");
        } else if (val instanceof Double) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Double");
            boxMethod = klass.getStaticMethod("valueOf", "(D)Ljava/lang/Double;");
        }
        return (Object) JavaCallUtil.javaCall(thread, boxMethod, null, val);
    }

    /**
     * 拆箱
     *
     * @param thread
     * @param val
     * @return
     */
    public static java.lang.Object unbox(Thread thread, Object val) {
        String name = val.getKlass().getName();
        //负责拆箱的方法
        Method unboxMethod = null;
        BootKlassLoader bootKlassLoader = KlassLoaderRegister.getBootKlassLoader();
        if (name.equals("java/lang/Integer")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Integer");
            unboxMethod = klass.getStaticMethod("intValue", "()I");
        } else if (name.equals("java/lang/Long")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Long");
            unboxMethod = klass.getStaticMethod("longValue", "()J");
        } else if (name.equals("java/lang/Boolean")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Boolean");
            unboxMethod = klass.getStaticMethod("booleanValue", "()Z");
        } else if (name.equals("java/lang/Byte")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Byte");
            unboxMethod = klass.getStaticMethod("byteValue", "()B");
        } else if (name.equals("java/lang/Character")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Character");
            unboxMethod = klass.getStaticMethod("charValue", "()C");
        } else if (name.equals("java/lang/Short")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Short");
            unboxMethod = klass.getStaticMethod("shortValue", "()S");
        } else if (name.equals("java/lang/Float")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Float");
            unboxMethod = klass.getStaticMethod("floatValue", "()F");
        } else if (name.equals("java/lang/Double")) {
            Klass klass = bootKlassLoader.loadKlass("java/lang/Double");
            unboxMethod = klass.getStaticMethod("doubleValue", "()D");
        } else {
            return val;
        }
        return JavaCallUtil.javaCall(thread, unboxMethod, val);
    }


}
